#include "PluginHelper.h"
using namespace yazi::engine;

#include "System.h"
#include "Singleton.h"
#include "Logger.h"
using namespace yazi::utility;

#include <dlfcn.h>



PluginHelper::PluginHelper(){

}

PluginHelper::~PluginHelper(){

}

void PluginHelper::load(const string &plugin){
    if(plugin.empty()){
        error("load plugin failed, plugin empty");
        return;
    }
    if(m_plugins.find(plugin) != m_plugins.end()){
        debug("pligin %s already loaded", plugin.c_str());
        return;
    }
    System* sys = Singleton<System>::instance();
    string dlpath = sys->get_root_path() + "/../plugin/" + plugin;
    void* handler = dlopen(dlpath.c_str(), RTLD_LAZY | RTLD_GLOBAL);
    if(handler == NULL){
        error("dlopen failed, path: %s, error:%s", dlpath.c_str(), dlerror());
        return;
    }
    m_plugins[plugin] = handler;
}

void PluginHelper::unload(const string &plugin){
    if(plugin.empty()){
        error("plugin empty");
        return;
    }
    auto it = m_plugins.find(plugin);
    if(it == m_plugins.end()){
        error("unload plugin failed, plugin %s not found", plugin.c_str());
        return;
    }
    dlclose(it->second);
    m_plugins.erase(it);
}

void *PluginHelper::get(const string &plugin, const string &symbol){
    if(plugin.empty()){
        error("plugin empty");
        return nullptr;
    }
    auto it = m_plugins.find(plugin);
    if(it == m_plugins.end()){
        load(plugin);
        it = m_plugins.find(plugin);
        if(it == m_plugins.end()){
            error("load plugin failed, plugin: %s", plugin.c_str());
            return NULL;
        }
    }
    void* func = dlsym(it->second, symbol.c_str());
    if(func == NULL){
        error("%s, plugin: %s, symbol: %s", dlerror(), plugin.c_str(), symbol.c_str());
    }
    return func;
}

void PluginHelper::show(){
    for(auto it = m_plugins.begin(); it != m_plugins.end(); ++it){
        debug("plugin: name = %s, handler = %x", it->first.c_str(), it->second);
    }
}